var board = []
var score = 0
var hasConflicted = []

var startx = 0
var starty = 0
var endx = 0
var endy = 0

$(document).ready(function () {
  prepareForMobile()
  newgame()
})


function prepareForMobile() {
  $('#grid-container').css('border-radius', 0.02 * gridContainerWidth);
  $('.grid-cell').css('border-radius', 0.02 * cellSideLength);
}

function newgame() {
  //初始化棋盘格
  init();
  //在随机两个格子生成数字
  generateOneNumber();
  generateOneNumber();
}

function init() {
  for (var i = 0; i < 4; i++)
    for (var j = 0; j < 4; j++) {
      var gridCell = $(`#grid-cell-${i}-${j}`)
      gridCell.css('top', getPosTop(i, j))
      gridCell.css('left', getPosLeft(i, j))

    }

  for (var i = 0; i < 4; i++) {
    board[i] = []
    hasConflicted[i] = []
    for (var j = 0; j < 4; j++) {
      board[i][j] = 0
      hasConflicted[i][j] = false
    }
  }

  updateBoardView();

  score = 0
  updateScore(score)
}


function updateBoardView() {
  $('.number-cell').remove()

  for (var i = 0; i < 4; i++)
    for (var j = 0; j < 4; j++) {
      var theNumberCell = $(`<div class="number-cell" id="number-cell-${i}-${j}"></div>`)
      if (board[i][j] == 0) {
        theNumberCell.css('top', getPosTop(i, j) + cellSideLength / 2)
        theNumberCell.css('left', getPosLeft(i, j) + cellSideLength / 2)
        theNumberCell.css('width', '0px')
        theNumberCell.css('height', '0px')
      } else {
        theNumberCell.css('top', getPosTop(i, j))
        theNumberCell.css('left', getPosLeft(i, j))
        theNumberCell.css('width', cellSideLength)
        theNumberCell.css('height', cellSideLength)
        theNumberCell.css('background-color', getNumberBackgroundColor(board[i][j]));
        theNumberCell.css('color', getNumberColor(board[i][j]));
        theNumberCell.text(board[i][j]);
      }

      hasConflicted[i][j] = false;
      $('#grid-container').append(theNumberCell)
    }

  $('.number-cell').css('border-radius', 0.02 * cellSideLength);
  $('.number-cell').css('line-height', cellSideLength + 'px');
  $('.number-cell').css('font-size', 0.6 * cellSideLength + 'px');
}

function generateOneNumber() {
  let loopCount = 0
  let x
  let y

  while (loopCount < 50) {
    x = Math.floor(Math.random() * 4)
    y = Math.floor(Math.random() * 4)

    if (board[x][y] === 0) {
      break
    }
    loopCount++
  }

  if (loopCount == 50) {
    for (var i = 0; i < 4; i++)
      for (var j = 0; j < 4; j++) {
        if (board[i][j] === 0) {
          x = i
          y = j
          break
        }
      }
  }

  var number = Math.random() < 0.5 ? 2 : 4
  board[x][y] = number
  showNumberWithAnimation(x, y, number);

  return true;
}

$(document).keydown(function (event) {
  event.preventDefault()
  switch (event.keyCode) {
    case 37:
      if (moveLeft()) {
        setTimeout("generateOneNumber()", 210);
        setTimeout("isgameover()", 300)
      }
      break;
    case 38: //up
      if (moveTop()) {
        setTimeout("generateOneNumber()", 210);
        setTimeout("isgameover()", 300);
      }
      break;
    case 39: //right
      if (moveRight()) {
        setTimeout("generateOneNumber()", 210);
        setTimeout("isgameover()", 300);
      }
      break;
    case 40: //down
      if (moveBottom()) {
        setTimeout("generateOneNumber()", 210);
        setTimeout("isgameover()", 300);
      }
      break;
    default: //default
      break;
  }
})



$(document).on('touchstart', function (event) {
  startx = event.originalEvent.touches[0].pageX
  starty = event.originalEvent.touches[0].pageY
})

$(document).on('touchend', function (event) {
  endx = event.originalEvent.changedTouches[0].pageX
  endy = event.originalEvent.changedTouches[0].pageY

  var deltax = endx - startx;
  var deltay = endy - starty;


  if (Math.abs(deltax) < gridContainerWidth * 0.1 && Math.abs(deltay) < gridContainerWidth * 0.1) {
    console.log('end');
    return
  }


  if (Math.abs(deltax) >= Math.abs(deltay)) {

    //move left
    if (deltax < 0) {
      console.log();
      if (moveLeft()) {
        setTimeout("generateOneNumber()", 210);
        setTimeout("isgameover()", 300)
      }
      return
    }

    //move right
    if (deltax > 0)
      if (moveRight()) {
        setTimeout("generateOneNumber()", 210);
        setTimeout("isgameover()", 300);
      }

  } else if (Math.abs(deltax) < Math.abs(deltay)) {

    //move Top
    if (deltay < 0) {
      if (moveTop()) {
        setTimeout("generateOneNumber()", 210);
        setTimeout("isgameover()", 300);
      }
      return
    }

    if (deltay > 0) {
      //move bottom
      if (moveBottom()) {
        setTimeout("generateOneNumber()", 210);
        setTimeout("isgameover()", 300);
      }
    }
  }


})





function isgameover() {
  if (nospace(board) && nomove(board)) {
    gameover()
  }
}

function gameover() {
  alert('gameover!')
}


function moveLeft() {
  if (nospace(board))
    if (!canMoveLeft(board))
      return


  for (var i = 0; i < 4; i++)
    for (var j = 1; j < 4; j++) {
      if (board[i][j] != 0) {

        for (let k = 0; k < j; k++) {
          if (board[i][k] == 0 && noBlockHorizontal(i, k, j, board)) {
            showMoveAnimation(i, j, i, k);
            board[i][k] = board[i][j]
            board[i][j] = 0
            break
          } else if (board[i][k] == board[i][j] && noBlockHorizontal(i, k, j, board)) {

            showMoveAnimation(i, j, i, k);
            board[i][k] += board[i][j]
            board[i][j] = 0

            score += board[i][k]
            updateScore(score);

            hasConflicted[i][k] = true

            break
          }
        }
      }
    }

  setTimeout("updateBoardView()", 200);
  return true
}


function moveRight() {
  if (nospace(board))
    if (!canMoveRight(board))
      return

  for (var i = 0; i < 4; i++)
    for (var j = 2; j >= 0; j--) {
      if (board[i][j] != 0) {
        for (let k = 3; k > j; k--) {
          if (board[i][k] == 0 && noBlockHorizontal(i, j, k, board)) {
            showMoveAnimation(i, j, i, k);
            board[i][k] = board[i][j]
            board[i][j] = 0
            break
          } else if (board[i][k] == board[i][j] && noBlockHorizontal(i, j, k, board)) {

            showMoveAnimation(i, j, i, k);
            board[i][k] += board[i][j]
            board[i][j] = 0

            score += board[i][k]
            updateScore(score);

            hasConflicted[i][k] = true

            break
          }
        }
      }
    }

  setTimeout("updateBoardView()", 200);
  return true
}

function moveTop() {
  if (nospace(board))
    if (!canMoveTop(board))
      return

  for (var j = 0; j < 4; j++)
    for (var i = 1; i < 4; i++) {
      if (board[i][j] != 0) {
        for (let k = 0; k < i; k++) {
          if (board[k][j] == 0 && noBlockVertical(j, k, i, board)) {
            showMoveAnimation(i, j, k, j);
            board[k][j] = board[i][j]
            board[i][j] = 0
            break
          } else if (board[k][j] == board[i][j] && noBlockVertical(j, k, i, board)) {
            showMoveAnimation(i, j, k, j);
            board[k][j] += board[i][j]
            board[i][j] = 0

            score += board[k][j]
            updateScore(score);

            hasConflicted[k][j] = true

            break
          }
        }
      }
    }

  setTimeout("updateBoardView()", 200);
  return true
}

function moveBottom() {
  if (nospace(board))
    if (!canMoveBottom(board))
      return

  for (var j = 0; j < 4; j++)
    for (var i = 2; i >= 0; i--) {
      if (board[i][j] != 0) {
        for (let k = 3; k > i; k--) {
          if (board[k][j] == 0 && noBlockVertical(j, i, k, board)) {
            showMoveAnimation(i, j, k, j);
            board[k][j] = board[i][j]
            board[i][j] = 0
            break
          } else if (board[k][j] == board[i][j] && noBlockVertical(j, i, k, board)) {
            showMoveAnimation(i, j, k, j);
            board[k][j] += board[i][j]
            board[i][j] = 0

            score += board[k][j]
            updateScore(score);

            hasConflicted[k][j] = true

            break
          }
        }
      }
    }

  setTimeout("updateBoardView()", 200);
  return true
}

